import * as Cesium from "cesium"
import { ControlUtils } from "./controlUtils";

export type LimitCameraOption = {
    maxHeight?: number,
    minHeight?: number,
    enableTilt?: boolean,
    enableRotate?: boolean,

}

export type coordAnd6Dof = {
    heading: number
    height: number
    latitude: number
    longitude: number
    pitch: number
    roll: number
}

/**
 * 相机相关工具类
 */
export class CameraUtils {
    constructor(private viewer: Cesium.Viewer, private controlUtils: ControlUtils) {
        
    }
    /**
     * 处理相机平移(鼠标左键平移)
     * @param cameraTranslationCallback 相机平移回调事件
     */
    private watchCameraTranslation(cameraTranslationCallback: () => void) {
        let removeMouseMove: (() => void);

        // 按下监听移动事件
        this.controlUtils.addMouseEventWatch(() => {
            // 鼠标移动触发相机平移事件
            removeMouseMove = this.controlUtils.addMouseEventWatch(() => {
                cameraTranslationCallback();
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

        // 抬起取消监听移动事件
        this.controlUtils.addMouseEventWatch(() => {
            if(removeMouseMove)
                removeMouseMove()
        }, Cesium.ScreenSpaceEventType.LEFT_UP);
    }
    /**
     * 处理相机缩放(鼠标滚轮缩放)
     */
    private watchCameraZoom(cameraZoomCallback: () => void) {
        this.controlUtils.addMouseEventWatch(() => {
            cameraZoomCallback();
        }, Cesium.ScreenSpaceEventType.WHEEL);
    }
    /**
     * 处理相机右键缩放(鼠标右键缩放)
     */
    private watchCameraRightZoom(cameraRightZoomCallback: () => void) {
        let removeMouseMove: (() => void);

        this.controlUtils.addMouseEventWatch(() => {
            removeMouseMove = this.controlUtils.addMouseEventWatch(() => {
                cameraRightZoomCallback();
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        }, Cesium.ScreenSpaceEventType.RIGHT_DOWN);
        this.controlUtils.addMouseEventWatch(() => {
            if(removeMouseMove)
                removeMouseMove()
        }, Cesium.ScreenSpaceEventType.RIGHT_UP)
    }
    /**
     * 监听相机倾斜
     * @param cameraTilt 
     */
    private watchCameraTilt(cameraTilt: () => void) {
        let removeMouseMove: (() => void);

        this.controlUtils.addMouseEventWatch(() => {
            removeMouseMove = this.controlUtils.addMouseEventWatch(() => {
                cameraTilt();
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        }, Cesium.ScreenSpaceEventType.MIDDLE_DOWN);
        this.controlUtils.addMouseEventWatch(() => {
            if(removeMouseMove)
                removeMouseMove()
        }, Cesium.ScreenSpaceEventType.MIDDLE_UP)
    }
    /**
     * 处理当前相机矩形是否超出范围矩形
     */
    private handleCurrentCameraRectangleWhetherExceedRange(range: {
        east: number,
        north: number,
        south: number,
        west: number
    }) {
        const currentRectangle = this.viewer.camera.computeViewRectangle(); // 当前相机的bbox(弧度指)
        if(currentRectangle){
            const cornerDegerValue = { // 当前相机的bbox(角度值)
                east: currentRectangle?.east / Math.PI * 180,
                north: currentRectangle?.north / Math.PI * 180,
                south: currentRectangle?.south / Math.PI * 180,
                west: currentRectangle?.west / Math.PI * 180
            }
            console.log(cornerDegerValue);
            const eastExceedRange = cornerDegerValue.east < range.east; // 超过最大east
            const northExceedRange = cornerDegerValue.north < range.north; // 超过最大north
            const southExceedRange = cornerDegerValue.south < range.south; // 超过最大south
            const westExceedRange = cornerDegerValue.west < range.west; // 超过最大west
            if(eastExceedRange || northExceedRange || southExceedRange || westExceedRange) {
                console.log("超出了")
            }
        }
    }
    /**
     * 限制相机范围(待开发)
     */
    private limitCameraArea() {
        /* 
            east
            : 
            1.9920222732020763
            north
            : 
            0.3944911912847686
            south
            : 
            0.3924099634996581
            west
            : 
            1.9888397770436042
        */
        const range = {
            east: 114.1344689505352,
            north: 22.602680315705285,
            south: 22.483434747413092,
            west: 113.95212535233814
        }
        this.watchCameraTranslation(() => {
            console.log("相机平移");
            this.handleCurrentCameraRectangleWhetherExceedRange(range);
        })
        this.watchCameraZoom(() => {
            console.log("相机缩放");
            this.handleCurrentCameraRectangleWhetherExceedRange(range);
        })
        this.watchCameraRightZoom(() => {
            console.log("相机右键缩放");
            this.handleCurrentCameraRectangleWhetherExceedRange(range);
        })
        this.watchCameraTilt(() => {
            console.log("相机倾斜");
            this.handleCurrentCameraRectangleWhetherExceedRange(range);
        })
    }
    /**
     * 通过坐标数组指定相机 有过度 的飞向指定位置
     * @param coord [x, y, z]（WGS84坐标）
     */
    flyToByCoordArray(coord: [number, number, number]) {
        this.viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(...coord)
        });
    }
    /**
     * 通过坐标数组指定相机 没有过度 的飞向指定位置
     * @param coord [经度, 维度, 高度]（WGS84坐标）
     */
    setViewByCoordArray(coord: [number, number, number]) {
        this.viewer.camera.setView({
            destination: Cesium.Cartesian3.fromDegrees(...coord)
        });
    }
    /**
     * 获取当前相机信息
     * {
     *      经度,
     *      维度,
     *      高度,
     *      pitch,
     *      heading,
     *      roll
     * }
     */
    getCameraInfo() {
        const catoPosition = this.viewer.camera.positionCartographic;
        return {
            latitude: Cesium.Math.toDegrees(catoPosition.latitude),
            longitude: Cesium.Math.toDegrees(catoPosition.longitude),
            height: catoPosition.height,
            pitch: this.viewer.camera.pitch,
            heading: this.viewer.camera.heading,
            roll: this.viewer.camera.roll
        }
    }
    /**
     * 添加指南针旋转监听(这个元素默认为向上是北方向)
     */
    addCompass(compassEl: HTMLDivElement) {
        return this.viewer.camera.changed.addEventListener(() => {
            const rotateAngle = Cesium.Math.toDegrees(
				this.viewer.camera.heading
			).toFixed(2);
			compassEl.style.transform = `rotateZ(${rotateAngle}deg)`;
        })
    }
    /**
     * 重置相机重新指向北方(heading为0)
     */
    resetCameraHeading() {
        const cameraInfo = this.getCameraInfo();
        this.viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(cameraInfo.longitude, cameraInfo.latitude, cameraInfo.height),
            orientation: {
                heading: 0,
                pitch: Cesium.Math.toRadians(cameraInfo.pitch),
                roll: Cesium.Math.toRadians(cameraInfo.roll)
            }
        });
    }
    /**
     * 相机限制（不想要限制的不传就行）
     * @param option 配置对象
     */
    limitCamera(option: LimitCameraOption) {
        if(option.maxHeight !== undefined) 
            this.viewer.scene.screenSpaceCameraController.maximumZoomDistance = option.maxHeight;  //相机高度的最大值
        if(option.minHeight !== undefined)
            this.viewer.scene.screenSpaceCameraController.minimumZoomDistance = option.minHeight;//相机的高度的最小值
        if(option.enableTilt !== undefined)
            this.viewer.scene.screenSpaceCameraController.enableTilt = option.enableTilt; // 是否允许相机倾斜
        if(option.enableRotate !== undefined)
            this.viewer.scene.screenSpaceCameraController.enableRotate = option.enableRotate; // 是否允许相机旋转
        
    }
    /**
     * 根据相机参数进行相机飞行(可以和getCameraInfo搭配)
     * @param option 相机参数
     */
    flyToByOption(option: coordAnd6Dof) {
        this.viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(option.longitude, option.latitude, option.height),
            orientation: {
                heading: option.heading,
                pitch: option.pitch,
                roll: option.roll
            }
        });
    }
}